package utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import services.SystemParamService;

import com.aton.db.Config;
import com.sun.management.OperatingSystemMXBean;

public class SystemTool {
	public static final Logger log=LoggerFactory.getLogger(SystemTool.class);
	//private final static float TotalBandwidth = 1000;   //网口带宽,默认1000Mbps  
	private static float TotalBandwidth = Float.parseFloat(SystemParamService.getValueByCacheId(BizConstants.PARAM_MAP.get("NETWORK_SPEED")));
	private static String netName=SystemParamService.getValueByCacheId(BizConstants.PARAM_MAP.get("NETWORK_NAME"));
	
	public final static String CPU = "CPU";
	public final static String DISK = "DISK";
	public final static String RAM = "RAM";
	public final static String NETWORK = "NETWORK";
	
	private static final int CPUTIME = 500;
	private static final int PERCENT = 100;
	private static final int FAULTLENGTH = 10;
	private final static String WINDOWS = "WINDOWS";
	private final static String LINUX = "LINUX";
	private final static long MB = 1024 * 1024;//数据单位MB
	 /** 
     * Purpose:采集CPU使用率 
     * @param args 
     * @return float,CPU使用率,小于1 
     */  
    private static float getLinuxCPUUsage() {  
        //log.info("开始收集cpu使用率");  
        float cpuUsage = 0;  
        Process pro1,pro2;  
        Runtime r = Runtime.getRuntime();  
        try {  
            String command = "cat /proc/stat";  
            //第一次采集CPU时间  
            //long startTime = System.currentTimeMillis();  
            pro1 = r.exec(command);
            BufferedReader in1 = new BufferedReader(new InputStreamReader(pro1.getInputStream()));  
            String line = null;  
            long idleCpuTime1 = 0, totalCpuTime1 = 0;   //分别为系统启动后空闲的CPU时间和总的CPU时间  
            while((line=in1.readLine()) != null){     
                if(line.startsWith("cpu")){  
                    line = line.trim();  
//                    log.info("获取CPU信息："+line);  
                    String[] temp = line.split("\\s+");
                    if(StringUtils.isNotEmpty(temp[4])){
                    	idleCpuTime1 = Long.parseLong(temp[4]); 
                    }
                    for(String s : temp){  
                        if(StringUtils.isNotEmpty(s)&&!s.equals("cpu")){  
                            totalCpuTime1 += Long.parseLong(s);  
                        }  
                    }     
                    //log.info("IdleCpuTime: " + idleCpuTime1 + ", " + "TotalCpuTime" + totalCpuTime1);  
                    break;  
                }                         
            }     
            in1.close();  
            pro1.destroy();  
            try {  
                Thread.sleep(100);  
            } catch (InterruptedException e) {  
                StringWriter sw = new StringWriter();  
                e.printStackTrace(new PrintWriter(sw));  
                log.error("CpuUsage休眠时发生InterruptedException. " + e.getMessage());  
                log.error(sw.toString());  
            }  
            //第二次采集CPU时间  
            //long endTime = System.currentTimeMillis();  
            pro2 = r.exec(command);  
            BufferedReader in2 = new BufferedReader(new InputStreamReader(pro2.getInputStream()));  
            long idleCpuTime2 = 0, totalCpuTime2 = 0;   //分别为系统启动后空闲的CPU时间和总的CPU时间  
            while((line=in2.readLine()) != null){     
                if(line.startsWith("cpu")){  
                    line = line.trim();  
                    //log.info(line);  
                    String[] temp = line.split("\\s+");  
                    if(StringUtils.isNotEmpty(temp[4])){
                    	idleCpuTime2 = Long.parseLong(temp[4]);  
                    }
                    for(String s : temp){  
                        if(StringUtils.isNotEmpty(s)&&!s.equals("cpu")){  
                            totalCpuTime2 += Long.parseLong(s);  
                        }  
                    }  
                   // log.info("IdleCpuTime: " + idleCpuTime2 + ", " + "TotalCpuTime" + totalCpuTime2);  
                    break;    
                }                                 
            }  
            if(idleCpuTime1 != 0 && totalCpuTime1 !=0 && idleCpuTime2 != 0 && totalCpuTime2 !=0){  
                cpuUsage = 1 - (float)(idleCpuTime2 - idleCpuTime1)/(float)(totalCpuTime2 - totalCpuTime1);  
                //log.info("本节点CPU使用率为: " + cpuUsage);  
            }                 
            in2.close();  
            pro2.destroy();  
        } catch (IOException e) {  
            StringWriter sw = new StringWriter();  
            e.printStackTrace(new PrintWriter(sw));  
            log.error("CpuUsage发生InstantiationException. " + e.getMessage());  
            log.error(sw.toString());  
        }     
		return cpuUsage*100;
    }  
    
    /** 
     * Purpose:采集内存使用率 
     * @param args 
     * @return float,内存使用率,小于1 
     */  
    private static Map<String,Object> getLinuxMemoryUsage() { 
    	Map<String,Object> map = new HashMap<String,Object>();
       // log.info("开始收集memory使用率");  
        float memUsage = 0.0f;  
        Process pro = null;  
        Runtime r = Runtime.getRuntime();  
        try {  
            String command = "cat /proc/meminfo";  
            pro = r.exec(command);  
            BufferedReader in = new BufferedReader(new InputStreamReader(pro.getInputStream()));  
            String line = null;  
            int count = 0;  
            long totalMem = 0, freeMem = 0;  
            while((line=in.readLine()) != null){      
//            	log.info("获取内存信息："+line);  
                String[] memInfo = line.split("\\s+");  
                if(memInfo[0].startsWith("MemTotal")&&StringUtils.isNotEmpty(memInfo[1])){  
                    totalMem = Long.parseLong(memInfo[1]);  
                }  
                if(memInfo[0].startsWith("MemFree")&&StringUtils.isNotEmpty(memInfo[1])){  
                    freeMem = Long.parseLong(memInfo[1]);  
                }  
                memUsage = 1- (float)freeMem/(float)totalMem;  
				map.put("memUsageRate", memUsage*100);
                map.put("freeMem", freeMem/MB);
                map.put("memUsage", (totalMem - freeMem) /MB);//以使用内存,单位MB
               // log.info("本节点内存使用率为: " + memUsage);   
                if(++count == 2){  
                    break;  
                }                 
            }  
            in.close();  
            pro.destroy();  
        } catch (IOException e) {  
            StringWriter sw = new StringWriter();  
            e.printStackTrace(new PrintWriter(sw));  
            log.error("MemUsage发生InstantiationException. " + e.getMessage());  
            log.error(sw.toString());  
        }     
        return map;  
    }  
    
    /** 
     * @Purpose:采集磁盘IO使用率 
     * @param args 
     * @return float,磁盘IO使用率,小于1 
     */  
    private static Map<String,Object> getLinuxDiskIOUsage() {  
    	Map<String,Object> map = new HashMap<String,Object>();
       // log.info("开始收集磁盘IO使用率");  
        float ioUsage = 0.0f;  
        Process pro = null;  
        Runtime r = Runtime.getRuntime();  
        try {  
            String command = "iostat -d -x";  
            pro = r.exec(command);  
            BufferedReader in = new BufferedReader(new InputStreamReader(pro.getInputStream()));  
            String line = null;  
            int count =  0;  
            while((line=in.readLine()) != null){
//            	log.info("获取IO信息："+line); 
                if(++count >= 4){  
                    String[] temp = line.split("\\s+");  
                    if(temp.length > 1){  
                        float util =  Float.parseFloat(temp[temp.length-1]);  
                        ioUsage = (ioUsage>util)?ioUsage:util;  
                    }  
                }  
            }  
			// if(ioUsage > 0){
               // log.info("本节点磁盘IO使用率为: " + ioUsage);      
			// ioUsage /= 100;
			// }
            map.put("diskUsageRate", ioUsage);
            in.close();  
            pro.destroy();  
        } catch (IOException e) {  
            StringWriter sw = new StringWriter();  
            e.printStackTrace(new PrintWriter(sw));  
            log.error("IoUsage发生InstantiationException. " + e.getMessage());  
            log.error(sw.toString());  
        }     
        return map;  
    }  
    
    /** 
     * @Purpose:采集网络带宽使用率 
     * @param args 
     * @return float,网络带宽使用率,小于1 
     */  
    private static Map<String,Object> getLinuxNetUsage() { 
    	Map<String,Object> map = new HashMap<String,Object>();
       // log.info("开始收集网络带宽使用率");  
        float netUsage = 0.0f;  
        float curRate = 0.0f;
        Process pro1,pro2;  
        Runtime r = Runtime.getRuntime();  
        try {  
            String command = "cat /proc/net/dev";  
            //第一次采集流量数据  
            long startTime = System.currentTimeMillis();  
            pro1 = r.exec(command);  
            BufferedReader in1 = new BufferedReader(new InputStreamReader(pro1.getInputStream()));  
            String line = null;  
            long inSize1 = 0, outSize1 = 0;  
            while((line=in1.readLine()) != null){  
                line = line.trim();  
//                log.info("获取网络带宽信息："+line); 
                if(line.contains(netName)){  
               //     log.info(line);  
                	String[] datelist = line.split(":");
                    String[] temp = datelist[1].split("\\s+");   
//					inSize1 = Long.parseLong(temp[0].substring(5)); // Receivebytes,单位为Byte
//					outSize1 = Long.parseLong(temp[8]); // Transmitbytes,单位为Byte
                    if(StringUtils.isNotEmpty(temp[0])){
                    	inSize1 = Long.parseLong(temp[0]);
                    }
                    if(StringUtils.isNotEmpty(temp[8])){
                    	outSize1 = Long.parseLong(temp[8]);
                    }
                    break;  
                }                 
            }     
            in1.close();  
            pro1.destroy();  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                StringWriter sw = new StringWriter();  
                e.printStackTrace(new PrintWriter(sw));  
                log.error("NetUsage休眠时发生InterruptedException. " + e.getMessage());  
                log.error(sw.toString());  
            }  
            //第二次采集流量数据  
            long endTime = System.currentTimeMillis();  
            pro2 = r.exec(command);  
            BufferedReader in2 = new BufferedReader(new InputStreamReader(pro2.getInputStream()));  
            long inSize2 = 0 ,outSize2 = 0;  
            while((line=in2.readLine()) != null){     
                line = line.trim();  
                if(line.contains(netName)){  
                  //  log.info(line);  
                	String[] datelist = line.split(":");
                    String[] temp = datelist[1].split("\\s+");  
//					inSize2 = Long.parseLong(temp[0].substring(5));
//					outSize2 = Long.parseLong(temp[8]);
                    if(StringUtils.isNotEmpty(temp[0])){
                    	inSize2 = Long.parseLong(temp[0]);
                    }
                    if(StringUtils.isNotEmpty(temp[8])){
                    	outSize2 = Long.parseLong(temp[8]);
                    }
                    break;  
                }                 
            }  
            if(inSize1 != 0 && outSize1 !=0 && inSize2 != 0 && outSize2 !=0){  
                float interval = (float)(endTime - startTime)/1000;  
				// 网口传输速度,单位为kbps
				curRate = (float) (inSize2 - inSize1 + outSize2 - outSize1)*8
						/ (1024 *1024 * interval);
                netUsage = curRate/TotalBandwidth;  
				map.put("netWorkUsageRate", netUsage * 100);// 使用率
                map.put("netWorkCurRate", curRate);//带宽
				// log.info("本节点网口速度为: " + curRate + "Kbps");
              //  log.info("本节点网络带宽使用率为: " + netUsage);  
            }                 
            in2.close();  
            pro2.destroy();  
        } catch (IOException e) {  
            StringWriter sw = new StringWriter();  
            e.printStackTrace(new PrintWriter(sw));  
            log.error("NetUsage发生InstantiationException. " + e.getMessage());  
            log.error(sw.toString());  
        }     
        return map;  
    }  
    
    private static float getWindowsCPUUsage(){
    	//long start = System.currentTimeMillis();
    	try {
			String procCmd = System.getenv("windir")
					+ "\\system32\\wbem\\wmic.exe process get Caption,CommandLine,KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount";
			// 取进程信息
			long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd));
			//Thread.sleep(CPUTIME);
			long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd));
			if (c0 != null && c1 != null) {
				long idletime = c1[0] - c0[0];
				long busytime = c1[1] - c0[1];
				return (float) (PERCENT * (busytime) * 1.0 / (busytime + idletime));
			} else {
				return 0;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			return 0;
		}/*finally {
			System.out.println(System.currentTimeMillis() - start);
		}*/
    }
    
 // 读取cpu相关信息
 	private static long[] readCpu(final Process proc) {
 		long[] retn = new long[2];
 		try {
 			proc.getOutputStream().close();
 			InputStreamReader ir = new InputStreamReader(proc.getInputStream());
 			LineNumberReader input = new LineNumberReader(ir);
 			String line = input.readLine();
 			if (line == null || line.length() < FAULTLENGTH) {
 				return null;
 			}
 			int capidx = line.indexOf("Caption");
 			int cmdidx = line.indexOf("CommandLine");
 			int rocidx = line.indexOf("ReadOperationCount");
 			int umtidx = line.indexOf("UserModeTime");
 			int kmtidx = line.indexOf("KernelModeTime");
 			int wocidx = line.indexOf("WriteOperationCount");
 			long idletime = 0;
 			long kneltime = 0;
 			long usertime = 0;
 			while ((line = input.readLine()) != null) {
 				if (line.length() < wocidx) {
 					continue;
 				}
 				// 字段出现顺序：Caption,CommandLine,KernelModeTime,ReadOperationCount,
 				// ThreadCount,UserModeTime,WriteOperation
 				String caption = substring(line, capidx, cmdidx - 1).trim();
 				String cmd = substring(line, cmdidx, kmtidx - 1).trim();
 				if (cmd.indexOf("wmic.exe") >= 0) {
 					continue;
 				}
 				String s1 = substring(line, kmtidx, rocidx - 1).trim();
 				String s2 = substring(line, umtidx, wocidx - 1).trim();
 				if (caption.equals("System Idle Process") || caption.equals("System")) {
 					if (s1.length() > 0)
 						idletime += Long.valueOf(s1).longValue();
 					if (s2.length() > 0)
 						idletime += Long.valueOf(s2).longValue();
 					continue;
 				}
 				if (s1.length() > 0)
 					kneltime += Long.valueOf(s1).longValue();
 				if (s2.length() > 0)
 					usertime += Long.valueOf(s2).longValue();
 			}
 			retn[0] = idletime;
 			retn[1] = kneltime + usertime;
 			return retn;
 		} catch (Exception ex) {
 			ex.printStackTrace();
 		} finally {
 			try {
 				proc.getInputStream().close();
 			} catch (Exception e) {
 				e.printStackTrace();
 			}
 		}
 		return null;
 	}
 	
 	/**
	 * 由于String.subString对汉字处理存在问题（把一个汉字视为一个字节)，因此在 包含汉字的字符串时存在隐患，现调整如下：
	 * 
	 * @param src
	 *            要截取的字符串
	 * @param start_idx
	 *            开始坐标（包括该坐标)
	 * @param end_idx
	 *            截止坐标（包括该坐标）
	 * @return
	 */
	private static String substring(String src, int start_idx, int end_idx) {
		byte[] b = src.getBytes();
		String tgt = "";
		for (int i = start_idx; i <= end_idx; i++) {
			tgt += (char) b[i];
		}
		return tgt;
	}
	/**
	 * 获取内存使用率
	 * @return
	 */
	private static Map<String,Object> getWindowsMemoryUasge(){
		Map<String,Object> map = new HashMap<String,Object>();
		OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
		// 总的物理内存+虚拟内存
		long totalvirtualMemory = osmxb.getTotalPhysicalMemorySize();
		// 剩余的物理内存
		long freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize(); 
		float compare = (float) (1 - freePhysicalMemorySize * 1.0 / totalvirtualMemory) * 100;
		map.put("memUsageRate", compare);
		map.put("freeMem", freePhysicalMemorySize/MB);
		map.put("memUsage", (totalvirtualMemory - freePhysicalMemorySize)/MB);//已使用内存MB
		return map;
	}
    
    public static Map<String,Object> getResourceInfoUsage(){
    	String system = System.getProperties().getProperty("os.name").toUpperCase();
    	Map<String,Object> map = new HashMap<String,Object>();
    	if(system.indexOf(WINDOWS)>=0){
			map.put("cpuUsageRate", getWindowsCPUUsage());
			map.putAll(getWindowsMemoryUasge());
			map.put("diskUsageRate", 0);
			map.put("netWorkUsageRate", 0);
    	}else if(system.indexOf(LINUX)>=0){
			map.put("cpuUsageRate", getLinuxCPUUsage());
			map.putAll(getLinuxMemoryUsage());
			map.putAll(getLinuxDiskIOUsage());
			map.putAll(getLinuxNetUsage());
    	}
    	return map;
    }
}
